package com.husky.diyservice.common;

import com.husky.diyservice.common.annotation.ChannelProxyServiceAnnotation;
import com.husky.diyservice.common.general.ChannelProxyEnum;
import com.husky.diyservice.utils.ApplicationContextUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import javax.annotation.PostConstruct;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author husky
 * @Date 2022/12/13 16:15
 * @Description: 使用时注意声明类泛型
 **/
@Slf4j
@Component
public class ChannelProxyDispatchFactory<T> {

    private Map<String, Object> channelMap =new ConcurrentHashMap<>(16);

    @Autowired
    private ApplicationContextUtils applicationContextUtils;

    /**
     * 初始化授权服务
     */
    @PostConstruct
    public void init() throws Exception {

        log.info("初始化校验 渠道枚举值");
        ChannelProxyEnum[] values = ChannelProxyEnum.values();
        Map<String,ChannelProxyEnum> map = new ConcurrentHashMap<>(16);
        for(ChannelProxyEnum cp:values){
            if(map.containsKey(cp.getChannelType())){
                throw new Exception("枚举类渠道类型重复["+cp+","+map.get(cp.getChannelType())+"]");
            }else{
                map.put(cp.getChannelType(),cp);
            }
        }

        //使用完毕清空map
        map.clear();
        log.info("初始化校验 渠道枚举值 结束");

        ApplicationContext context = applicationContextUtils.getApplicationContext();
        Map<String, Object> beanMap = context.getBeansWithAnnotation(ChannelProxyServiceAnnotation.class);
        // 得到所有的实现类
        // Map<String, T> beanMap = context.getBeansOfType(tClass);
        for (Map.Entry<String, Object> channelProxyServiceEntry : beanMap.entrySet()) {
            Class<?> targetClass = AopUtils.getTargetClass(channelProxyServiceEntry.getValue());
            ChannelProxyServiceAnnotation channelServiceInfo = targetClass.getAnnotation(ChannelProxyServiceAnnotation.class);
            if(null == channelServiceInfo){
                log.error("渠道名称未设置,class:{},channel:{}",targetClass.getName(), ChannelProxyServiceAnnotation.class.getName());
                throw new Exception("服务:"+targetClass.getName()+" 需要配置对应的渠道名称");
            }
            channelMap.put(channelServiceInfo.channelInfo().getChannelType(),channelProxyServiceEntry.getValue());
        }
    }


    /**
     * 获取服务
     *
     * @param channelType 服务类型
     * @return
     */
    public T getService(String channelType) throws Exception {

        Assert.state(channelMap.containsKey(channelType),"无效的渠道类型");
        return (T) channelMap.get(channelType);

    }


}